package com.yanqu.road.server.manger.activity.daomu;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.entity.activity.daomu.DaoMuAttribute;
import com.yanqu.road.entity.activity.daomu.DaoMuReward;
import com.yanqu.road.entity.activity.daomu.DaoMuSkill;
import com.yanqu.road.entity.activity.daomu.DaoMuStatementInfo;
import com.yanqu.road.entity.activity.daomu.config.*;
import com.yanqu.road.entity.activity.daomu.data.DaoMuActivityUserCollectionData;
import com.yanqu.road.entity.activity.daomu.data.DaoMuActivityUserData;
import com.yanqu.road.entity.activity.daomu.data.DaoMuActivityUserOfferRewardData;
import com.yanqu.road.entity.activity.daomu.enums.DaoMuActivityChildTypeEnum;
import com.yanqu.road.entity.activity.daomu.enums.DaoMuCurioTypeEnum;
import com.yanqu.road.entity.activity.daomu.enums.DaoMuOfferRewardStatusEnum;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.daomu.*;
import com.yanqu.road.exception.BusinessException;
import com.yanqu.road.logic.bussiness.activity.DaoMuActivityBusiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.pb.activity.DaoMuProto;
import com.yanqu.road.pb.activity.DaoMuPvpProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.passRoad.PassRoadModule;
import com.yanqu.road.server.gameplayer.module.player.AttributeModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.logic.activity.condition.daomu.DaoMuPvePersonRankArgs;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.TempCommonMgr;
import com.yanqu.road.server.manger.activity.daomu.pb.DaoMuActivityPb;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.PassRoadMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.UUIDHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.omg.CORBA.Current;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class DaoMuActivityUser {

    protected static Logger logger = LogManager.getLogger(DaoMuActivityUser.class.getName());

    private GamePlayer player;

    private DaoMuActivityConfig daoMuActivityConfig;

    //落地数据-玩家信息
    private DaoMuActivityUserData daoMuActivityUserData;

    //落地数据-玩家藏品信息
    private Map<Integer, DaoMuActivityUserCollectionData> userCollectionDataMap = new ConcurrentHashMap<>();

    //落地数据-玩家关卡悬赏信息.K:关卡id。V:NPC悬赏信息（k：npcId，悬赏信息）
    private Map<Integer, Map<Integer, DaoMuActivityUserOfferRewardData>> userOfferRewardDataMap = new ConcurrentHashMap<>();

    //房间对象
    private DaoMuActivityPveRoom daoMuActivityPveRoom = null;

    //缓存的悬赏奖励，结算使用
    private Map<String, DaoMuReward> offerRewardCacheMap = new ConcurrentHashMap<>();

    /**
     * 构造函数
     * @param daoMuActivityUserData
     */
    public DaoMuActivityUser(GamePlayer player, DaoMuActivityConfig daoMuActivityConfig,
            DaoMuActivityUserData daoMuActivityUserData,
            Map<Integer, DaoMuActivityUserCollectionData> collectionDataMap,
            Map<Integer, Map<Integer, DaoMuActivityUserOfferRewardData>> offerRewardMap
    ) {
        this.player = player;
        this.daoMuActivityConfig = daoMuActivityConfig;
        this.daoMuActivityUserData = daoMuActivityUserData;
        this.userCollectionDataMap = collectionDataMap;
        this.userOfferRewardDataMap = offerRewardMap;
    }

    /**
     * 存储谁
     */
    public void saveData() {
        //玩家数据
        if(this.daoMuActivityUserData.isInsertOption()){
            DaoMuActivityBusiness.addUserData(this.daoMuActivityUserData);
        }else if(this.daoMuActivityUserData.isUpdateOption()){
            DaoMuActivityBusiness.updateUserData(this.daoMuActivityUserData);
        }
        //藏品数据
        for (DaoMuActivityUserCollectionData daoMuActivityUserCollectionData : this.userCollectionDataMap.values()) {
            if(daoMuActivityUserCollectionData.isInsertOption()){
                DaoMuActivityBusiness.addCollectionData(daoMuActivityUserCollectionData);
            }else if(daoMuActivityUserCollectionData.isUpdateOption()){
                DaoMuActivityBusiness.updateCollectionData(daoMuActivityUserCollectionData);
            }
        }
        //悬赏信息
        for (Map<Integer, DaoMuActivityUserOfferRewardData> offerRewardDataMap : this.userOfferRewardDataMap.values()) {
            for (DaoMuActivityUserOfferRewardData offerRewardData : offerRewardDataMap.values()) {
                if(offerRewardData.isInsertOption()){
                    DaoMuActivityBusiness.addOfferRewardData(offerRewardData);
                }else if(offerRewardData.isUpdateOption()){
                    DaoMuActivityBusiness.updateOfferRewardData(offerRewardData);
                }
            }
        }
    }

    public void setDaoMuActivityConfig(DaoMuActivityConfig daoMuActivityConfig) {
        this.daoMuActivityConfig = daoMuActivityConfig;
    }

    /**
     * 玩家藏品MAP
     * @return
     */
    public Map<Integer, DaoMuActivityUserCollectionData> getUserCollectionDataMap() {
        return userCollectionDataMap;
    }

    /**
     * 获取房间
     * @return
     */
    public DaoMuActivityPveRoom getDaoMuActivityPveRoom() {
        return daoMuActivityPveRoom;
    }

    /**
     * 获取历史最高关卡
     * @return
     */
    public int getHistoryMaxPassesId() {
//        if (this.daoMuActivityConfig.getActivityInfo().getChildType() == DaoMuActivityChildTypeEnum.DAOMU.getType()) {
//            return (int) player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.DaoMuMaxPassesId);
//        } else if (this.daoMuActivityConfig.getActivityInfo().getChildType() == DaoMuActivityChildTypeEnum.MON_JIN.getType()){
//            return (int) player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MonJinMaxPassesId);
//        }
//        return 0;
        long daoMuMaxPassesId = (int) player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.DaoMuMaxPassesId);
        long monJinMaxPassesId = (int) player.getModule(AttributeModule.class).getAttribute(ePlayerAttrType.MonJinMaxPassesId);
        return (int) Math.max(daoMuMaxPassesId, monJinMaxPassesId);
    }

    /**
     * set 历史最高关卡
     * @param passesId
     */
    public void setHistoryMaxPassesId(int passesId) {
//        if (this.daoMuActivityConfig.getActivityInfo().getChildType() == DaoMuActivityChildTypeEnum.DAOMU.getType()) {
            player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.DaoMuMaxPassesId, passesId);
//        } else if (this.daoMuActivityConfig.getActivityInfo().getChildType() == DaoMuActivityChildTypeEnum.MON_JIN.getType()){
//            player.getModule(AttributeModule.class).setAttribute(ePlayerAttrType.MonJinMaxPassesId, passesId);
//        }
    }

    /**
     * 获取玩家ID
     * @return
     */
    public long getUserId() {
        return this.daoMuActivityUserData.getUserId();
    }

    /**
     * 获取玩家区服ID
     * @return
     */
    public long getServerId() {
        return this.daoMuActivityUserData.getServerId();
    }

    public int getActivityId(){
        return this.daoMuActivityUserData.getActivityId();
    }

    /**
     * 通过上一个关卡的时间
     * @return
     */
    public long getPassPrePassesTime() {
        return this.daoMuActivityUserData.getPassPrePassesTime();
    }

    /**
     * 获取关卡ID
     * @return
     */
    public int getPassesId() {
        return this.daoMuActivityUserData.getPassesId();
    }

    /**
     * 获取是否通关
     * @return
     */
    public int getPassAllFlag() {
        return this.daoMuActivityUserData.getPassAllFlag();
    }

    /**
     * 获取角色ID
     * @return
     */
    public int getRoleId() {
        return this.daoMuActivityUserData.getRoleId();
    }

    /**
     * 获取体力
     * @return
     */
    public int getEnergy() {
        return this.daoMuActivityUserData.getEnergy();
    }

    /**
     * 当前摸金进度宝箱ID
     * @return
     */
    public int getProgressBoxId() {
        return this.daoMuActivityUserData.getProgressBoxId();
    }

    /**
     * 摸金进度
     * @return
     */
    public int getBoxProgress() {
        return this.daoMuActivityUserData.getBoxProgress();
    }

    /**
     * 获取藏品分
     * @return
     */
    public long getCollectionScore() {
        return this.daoMuActivityUserData.getCollectionScore();
    }

    /**
     * set藏品分
     * @param collectionScore
     */
    public void setCollectionScore(long collectionScore) {
        this.daoMuActivityUserData.setCollectionScore(collectionScore);
    }

    /**
     * 自选技能ID
     */
    public int getSelectSkillId() {
        return this.daoMuActivityUserData.getSelectSkillId();
    }

    /**
     * 获取摸金等级
     */
    public int getTouchGoldLevel() {
        return this.daoMuActivityUserData.getLevel();
    }

    /**
     * set摸金等级
     * @param level
     */
    public void setTouchGoldLevel(int level) {
        this.daoMuActivityUserData.setLevel(level);
    }

    /**
     * 获取道具
     * @return
     */
    public String getProp() {
        return this.daoMuActivityUserData.getProp();
    }

    /**
     * 血脉关卡击杀数量
     * @return
     */
    public Map<String, Integer> getXmKillNumMap() {
        return daoMuActivityUserData.getKillNumJson();
    }

    /**
     * 获取解锁的角色,逗号隔开
     * @return
     */
    public String getUnlockRoleIds() {
       return this.daoMuActivityUserData.getUnlockRoles();
    }

    /**
     * 首通奖励记录
     * @param passesId
     */
    public void addFirstRewardPassesId(int passesId) {
        this.daoMuActivityUserData.addFirstRewardRecord(passesId);
    }

    /**
     * 判断是否首通过，true：是，false：否
     * @param passesId
     * @return
     */
    public boolean getAlreadyFirstPass(int passesId) {
        return this.daoMuActivityUserData.getFirstRewardRecord().contains(passesId);
    }

    /**
     * 获取过关的关卡IDS
     * @return
     */
    public Set<Integer> getPassPassesIds() {
        return this.daoMuActivityUserData.getFirstRewardRecord();
    }

    /**
     * 获取通过的最高关卡，0：未通过任何关卡
     * @return
     */
    public int getPassMaxPassesId() {
        //判断是否通关
        if (this.getPassAllFlag() == 1) {
            return this.getPassesId();
        }
        //未通关
        int firstPassesId = this.daoMuActivityConfig.getDefaultPassesId();
        if (this.getPassesId() > firstPassesId) {
            //获取当前关卡的上一个关卡,也就是通过的最高关卡
            return this.daoMuActivityConfig.getPrePassesId(this.getPassesId());
        }
        return 0;
    }

    /**
     * 获取已解锁的角色ID SET
     * @return
     */
    public Set<Integer> getUnlockRoleIdSet() {
        String[] roleIdStrArr = this.getUnlockRoleIds().split(",");
        Set<Integer> unlockRoleIdSet = new HashSet<>();
        for (String roleIdStr : roleIdStrArr) {
            unlockRoleIdSet.add(Integer.parseInt(roleIdStr));
        }
        return unlockRoleIdSet;
    }

    /**
     * 关卡悬赏数据
     * @return
     */
    public Map<Integer, Map<Integer, DaoMuActivityUserOfferRewardData>> getUserOfferRewardDataMap() {
        return userOfferRewardDataMap;
    }

    /**
     * 选择角色
     * @param roleId
     */
    public void selectRole(int roleId) throws BusinessException {
        //判断角色是否解锁
        boolean unlockFlag = false;
        String[] roleIdArr = this.getUnlockRoleIds().split(",");
        for (String roleIdStr : roleIdArr) {
            int unlockRoleId = Integer.valueOf(roleIdStr);
            if (unlockRoleId == roleId) {
                unlockFlag = true;
            }
        }
        if (!unlockFlag) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_ROLE_NOT_UNLOCK_ERROR);
        }
        this.daoMuActivityUserData.setRoleId(roleId);
    }

    /**
     * 增加道具
     * @param property
     */
    public void addProp(Property property) {
        Property myProperty = PropertyHelper.parseStringToProperty(this.daoMuActivityUserData.getProp());
        if (myProperty == null) {
            myProperty = new Property();
        }
        myProperty.addProperty(property);
        this.daoMuActivityUserData.setProp(PropertyHelper.parsePropertyToString(myProperty));
        //判断道具是否是藏品,增加藏品总获取数量
        for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
            int propId = entry.getKey();
            BigInteger propNum = entry.getValue();
            DaoMuCurioConfig daoMuCurioConfig = daoMuActivityConfig.getDaoMuCurioConfigMap().get(propId);
            if (daoMuCurioConfig != null && daoMuCurioConfig.getType() == DaoMuCurioTypeEnum.TYPE_COLLECTION.getType()) {
                this.addCollectionPropNum(daoMuCurioConfig.getCurioId(), propNum.intValue());
            }
        }
    }

    /**
     * 减少道具
     * @param propId
     * @param num
     */
    public void reProp(int propId, int num) throws BusinessException {
        Property property = PropertyHelper.parseStringToProperty(this.daoMuActivityUserData.getProp());
        if (property == null) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_PROP_NOT_ENOUGH);
        }
        boolean result = property.removeProperty(propId, BigInteger.valueOf(num));
        if (!result) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_PROP_NOT_ENOUGH);
        }
        this.daoMuActivityUserData.setProp(PropertyHelper.parsePropertyToString(property));
    }

    /**
     * 增加摸金次数
     * @param num
     */
    public void addTouchBoxNum(int num) {
        int oldNum = this.daoMuActivityUserData.getDrawBoxNum();
        int newNum = oldNum + num;
        this.daoMuActivityUserData.setDrawBoxNum(newNum);
    }

    /**
     * 减少体力
     * @param num
     */
    public void reEnergy(int num) throws BusinessException {
        //自然恢复体力
        this.restoreEnergy();
        //计算剩余体力
        int newNum = this.getEnergy() - num;
        if (newNum < 0) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_ENERGY_NOT_ENOUGH);
        }
        this.daoMuActivityUserData.setEnergy(newNum);
    }

    /**
     * 自然恢复体力
     */
    private void restoreEnergy () {
        //自然恢复体力处理
        long lastRestoreTime = this.daoMuActivityUserData.getLastRestoreTime();
        int cd = Integer.valueOf(daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.DAOMU_ENERGY_CD));
        int cdNum = Integer.valueOf(daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.DAOMU_ENERGY_CD_NUM));
        int maxEnergy = Integer.valueOf(daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.DAOMU_ENERGY_LIMIT));
        int energy = this.daoMuActivityUserData.getEnergy();
        CalcPowerResult calcPowerResult = PowerHelper.calcPower(lastRestoreTime, cd, cdNum, maxEnergy, energy);
        this.daoMuActivityUserData.setEnergy(calcPowerResult.getCurPower());
        this.daoMuActivityUserData.setLastRestoreTime(calcPowerResult.getLastRecoverTime());
    }

//    /**
//     * 过关的话，是否首通
//     * @param passesId
//     * @return
//     */
//    private boolean checkPassIsFirst(int passesId) {
//        if (this.getPassAllFlag() > 0) {
//            return false;
//        }
//        if (passesId == this.getPassesId()) {
//            return true;
//        }
//        return false;
//    }

    /**
     * 过关的话，是否首通
     * @param passesId
     * @return
     */
    private boolean checkPassIsFirst(int passesId) {
        boolean alreadyPassFlag = this.getAlreadyFirstPass(passesId);
        return !alreadyPassFlag;
    }

    /**
     * 扫荡
     * @param passesId 关卡ID
     * @return 奖励
     */
    public DaoMuReward mopUp(int passesId) throws BusinessException {
        //判断关卡是否可以扫荡
        if (this.daoMuActivityUserData.getPassesId() <= passesId) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_NOT_PASS_PASSES);
        }
        //增加道具
        DaoMuReward daoMuReward = this.daoMuActivityConfig.getPassesReward(passesId, true, false);
        //增加活动道具，通用道具要返回区服增加
        Property property = daoMuReward.getActivityReward();
        this.addProp(property);
        //返回
        return daoMuReward;
    }

    /**
     * 添加藏品数量
     * @param collectionId
     * @param collectionPropNum
     * @return
     */
    public DaoMuActivityUserCollectionData addCollectionPropNum(int collectionId, int collectionPropNum) {
        DaoMuActivityUserCollectionData userCollectionData = this.userCollectionDataMap.get(collectionId);
        if (userCollectionData == null) {
            userCollectionData = new DaoMuActivityUserCollectionData();
            userCollectionData.setActivityId(this.daoMuActivityConfig.getActivityId());
            userCollectionData.setCollectionId(collectionId);
            userCollectionData.setCollectionLevel(0);
            userCollectionData.setCollectionPropNum(collectionPropNum);
            userCollectionData.setUserId(this.getUserId());
            userCollectionData.setCreateTime(System.currentTimeMillis());
            userCollectionData.setInsertOption();
            this.userCollectionDataMap.put(collectionId, userCollectionData);
        } else {
            int newNum = userCollectionData.getCollectionPropNum() + collectionPropNum;
            userCollectionData.setCollectionPropNum(newNum);
        }
        //返回
        return userCollectionData;
    }

    /**
     * 同步到跨服报名榜单
     */
    public void notifyPvpApply() {
        // 上报跨服
        DaoMuPvpProto.DaoMuPvpUserApplyReqMsg.Builder builder = DaoMuPvpProto.DaoMuPvpUserApplyReqMsg.newBuilder();
        builder.setActivityId(getActivityId());
        // 同步
        builder.setType(0);
        builder.setCollectionLevel(this.getTouchGoldLevel());
        builder.setCollectionScore(this.getCollectionScore());
        builder.setPlayerInfo(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
        // 上跨服
        player.sendPacket(Protocol.C_CROSS_DAOMU_PVP_USER_APPLY, builder);
    }

    /**
     * 藏品升级-批量
     */
    public void batchCollectionUpgrade() {
        for (DaoMuActivityUserCollectionData data : this.userCollectionDataMap.values()) {
            try {
                this.collectionUpgrade(data.getCollectionId(), false);
            } catch (BusinessException e) {
                logger.error("盗墓笔记-批量升级错误：{}, {}", e.getCode(), e.getMsg());
            }
        }
    }

    /**
     * 藏品升级
     * @param collectionId 藏品ID
     * @param doActive 是否处理激活（0级只能升到1级），true：要，false: 不用
     * @return DaoMuActivityUserCollectionData
     */
    public DaoMuActivityUserCollectionData collectionUpgrade(int collectionId, boolean doActive) throws BusinessException {
        DaoMuActivityUserCollectionData userCollectionData = this.userCollectionDataMap.get(collectionId);
        //藏品是否存在
        if (userCollectionData == null) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_COLLECT_NOT_EXIST);
        }
        //旧等级，旧属性
        int oldLevel = userCollectionData.getCollectionLevel();
        Map<Integer, DaoMuAttribute> oldAttribute = this.getAttributeMap();

        //一键升级
        while (true) {
            try {
                //下个等级
                int level = userCollectionData.getCollectionLevel() + 1;
                DaoMuCurioConfig daoMuCurioConfig = this.daoMuActivityConfig.getCollectionInfo(collectionId, level);
                if (daoMuCurioConfig == null) {
                    throw BusinessException.newException(GameErrorCode.E_DAOMU_COLLECT_NOT_EXIST);
                }
                //消耗藏品碎片
                String costPropStr = daoMuCurioConfig.getCost();
                String[] costPropStrArr = costPropStr.split("=");
                int costPropId = Integer.valueOf(costPropStrArr[0]);
                int costPropNum = Integer.valueOf(costPropStrArr[1]);
                this.reProp(costPropId, costPropNum);
                //升级
                userCollectionData.setCollectionLevel(level);
            } catch (BusinessException e) {
               break;
            }
            if (doActive) {
                //0升到1级，不走一键升级
                if (oldLevel == 0) {
                    break;
                }
            }
        }
        //升级后处理
        if (userCollectionData.getCollectionLevel() > oldLevel) {
            //计算玩家藏品分
            this.countCollectionScore();
            //日志
            LogDaoMuCollectionUpgrade log = new LogDaoMuCollectionUpgrade();
            log.setActivityId(this.daoMuActivityConfig.getActivityId());
            log.setUserId(this.getUserId());
            log.setCollectionId(collectionId);
            log.setPreLevel(oldLevel);
            log.setPrePower(0L);
            log.setPreAttribute(this.attributeMapToString(oldAttribute));
            log.setLevel(userCollectionData.getCollectionLevel());
            log.setPower(0L);
            log.setAttribute(this.attributeMapToString(this.getAttributeMap()));
            AutoLogMgr.add(log);
        }
        return userCollectionData;
    }

    /**
     * 属性map转字符串
     * @param attributeMap
     * @return
     */
    private String attributeMapToString(Map<Integer, DaoMuAttribute> attributeMap) {
        Map<Integer, BigDecimal> map = new HashMap<>();
        for (DaoMuAttribute daoMuAttribute : attributeMap.values()) {
            map.put(daoMuAttribute.getId(), daoMuAttribute.getValue());
        }
        return JSONObject.toJSONString(map);
    }

    /**
     * 使用道具恢复体力
     * @param prop
     * @return
     */
    public int usePropRecoverEnergy(String prop) {
        //自然恢复体力
        this.restoreEnergy();
        //获取需要增加多少体力
        String[] propArr = prop.split("=");
        int propId = Integer.valueOf(propArr[0]);
        int propNum = Integer.valueOf(propArr[1]);
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(propId);
        if (goodsInfo == null) {
            return this.getEnergy();
        }
        //一个体力包恢复多少体力
        int oneNum = goodsInfo.getParamList().get(0).intValue();
        int addEnergy = propNum * oneNum;
        int newEnergy = this.getEnergy() + addEnergy;
        this.daoMuActivityUserData.setEnergy(newEnergy);
        return newEnergy;
    }

    /**
     * 计算玩家藏品分
     * @return
     */
    public long countCollectionScore() {
        long collectionScore = 0;
        for (DaoMuActivityUserCollectionData info : this.userCollectionDataMap.values()) {
            if (info.getCollectionLevel() > 0) {
                //单个藏品分
                DaoMuCurioConfig config = daoMuActivityConfig.getCollectionInfo(info.getCollectionId(), info.getCollectionLevel());
                collectionScore += config.getFavoriteScore();
            }
        }
        this.setCollectionScore(collectionScore);

        //更新摸金等级
        this.countTouchGoldLevel();

        //盗墓笔记才进行处理
        if (this.daoMuActivityConfig.getActivityInfo().getType() == eActivityType.DaoMu.getValue()) {
            //成就变化
            player.notifyListener(eGamePlayerEventType.DaoMuAchievementCollectionScore.getValue(), this.getCollectionScore());
            //排行变动
            this.notifyPveRank();
            // 通知pvp榜单更新
            this.notifyPvpApply();
        }

        return collectionScore;
    }

    /**
     * 排行变动
     */
    private void notifyPveRank() {
        //获取通过的最高关卡
        int passMaxPassesId = this.getPassMaxPassesId();
        if (passMaxPassesId > 0) {
            //排行变动
            player.notifyListener(eGamePlayerEventType.DaoMuPvePersonRank.getValue(), new DaoMuPvePersonRankArgs(passMaxPassesId, getCollectionScore()));
        }
    }

//    /**
//     * 获取玩家解锁的技能MAP
//     * @return
//     */
//    public Map<Integer, DaoMuSkill> getUnlockSkillMap() {
//        Map<Integer, DaoMuSkill> map = new HashMap<>();
//        for (DaoMuActivityUserCollectionData info : this.userCollectionDataMap.values()) {
//            if (info.getCollectionLevel() <= 0) {
//                continue;
//            }
//            DaoMuCurioConfig daoMuCurioConfig = this.daoMuActivityConfig.getCollectionInfo(info.getCollectionId(), 1);
//            if (daoMuCurioConfig != null) {
//                //判断藏品是否解锁-是否达到解锁关卡
//                if (this.getPassesId() > daoMuCurioConfig.getUnlockCond() || this.getPassAllFlag() == 1) {
//                    //去除别人的专属技能
//                    int skillUnId = Integer.parseInt(daoMuCurioConfig.getUnlockSkillLevel());
//                    int skillRoleId = this.checkSkillIsExclusive(skillUnId);
//                    if (skillRoleId == 0 || skillRoleId == this.getRoleId()) {
//                        DaoMuSkillConfig daoMuSkillConfig = this.daoMuActivityConfig.getDaoMuSkillConfigMap().get(Integer.valueOf(daoMuCurioConfig.getUnlockSkillLevel()));
//                        DaoMuSkill daoMuSkill = new DaoMuSkill();
//                        daoMuSkill.setSkillId(daoMuSkillConfig.getSkillId());
//                        daoMuSkill.setSkillLevel(daoMuSkillConfig.getLevel());
//                        daoMuSkill.setCollectionId(daoMuCurioConfig.getCurioId());
//                        map.put(daoMuSkill.getSkillId(), daoMuSkill);
//                    }
//                }
//            }
//        }
//        return map;
//    }

    /**
     * 获取玩家解锁的技能MAP
     * @return
     */
    public Map<Integer, DaoMuSkill> getUnlockSkillMap() {
        Map<Integer, DaoMuSkill> map = new HashMap<>();
        for (DaoMuCollectionConfig daoMuCollectionConfig : this.daoMuActivityConfig.getCollectionConfigMap().values()){
            if (this.getPassesId() > daoMuCollectionConfig.getUnlockCond()) {
                DaoMuSkillConfig daoMuSkillConfig = this.daoMuActivityConfig.getDaoMuSkillConfigMap().get(daoMuCollectionConfig.getUnlockSkillLevel());
                //去除别人的专属技能
                int skillRoleId = this.checkSkillIsExclusive(daoMuSkillConfig.getSkillId());
                if (skillRoleId == 0 || skillRoleId == this.getRoleId()) {
                    DaoMuSkill daoMuSkill = new DaoMuSkill();
                    daoMuSkill.setSkillId(daoMuSkillConfig.getSkillId());
                    daoMuSkill.setSkillLevel(1);
                    daoMuSkill.setCollectionId(daoMuCollectionConfig.getCurioId());
                    map.put(daoMuSkill.getSkillId(), daoMuSkill);
                }
            }
        }
        return map;
    }

    /**
     * 判断技能是否是专属
     * @param skillId 技能ID
     * @return 返回专属角色ID。不是专属技能，返回0
     */
    private int checkSkillIsExclusive(int skillId) {
        Map<Integer, Integer> roleCurioIdMap = this.getRoleMap();
        for (Map.Entry<Integer, Integer> entry : roleCurioIdMap.entrySet()) {
            int roleId = entry.getKey();
            int roleCurioUnId = entry.getValue();
            //主动技能
            DaoMuCurioConfig roleCurioInfo = this.daoMuActivityConfig.getDaoMuCurioConfigMap().get(roleCurioUnId);
            int roleSkillUnId = Integer.valueOf(roleCurioInfo.getUnlockSkillLevel());
            DaoMuSkillConfig daoMuSkillConfig = this.daoMuActivityConfig.getDaoMuSkillConfigMap().get(roleSkillUnId);
            if (daoMuSkillConfig.getSkillId() == skillId) {
                return roleId;
            }
            //被动技能
            DaoMuSkillConfig roleSkillConfig = this.daoMuActivityConfig.getDaoMuSkillConfigMap().get(roleSkillUnId);
            if (roleSkillConfig.getCombSkill() == skillId) {
                return roleId;
            }
        }
        return 0;
    }

    /**
     * 获取未解锁的专属藏品ID SET
     */
    private Set<Integer> getLockExclusiveCollectionSet() {
        Set<Integer> set = new HashSet<>();
        //已解锁角色
        Set<Integer> unlockRoleIdSet = this.getUnlockRoleIdSet();
        //专属藏品id，角色关系map
        Map<Integer, Integer> collectionRoleMap = this.getCollectionRoleMap();
        //注入SET
        for (Map.Entry<Integer, Integer> entry : collectionRoleMap.entrySet()) {
            int curioUnId = entry.getKey();
            int roleId = entry.getValue();
            if (!unlockRoleIdSet.contains(roleId)) {
                DaoMuCurioConfig curioInfo = this.daoMuActivityConfig.getDaoMuCurioConfigMap().get(curioUnId);
                set.add(curioInfo.getCurioId());
            }
        }
        return set;
    }

    /**
     * 添加PVE对局内产生的局外道具
     * @param pickUpPropId
     */
    public void addPvePickUpProp(int pickUpPropId) {
        //判断是否是局外道具
        DaoMuCurioConfig daoMuCurioConfig = this.daoMuActivityConfig.getDaoMuCurioConfigMap().get(pickUpPropId);
        if (daoMuCurioConfig != null && !DaoMuCurioTypeEnum.checkBattleProp(daoMuCurioConfig.getType())) {
            Property property = new Property();
            property.setGood(pickUpPropId, BigInteger.valueOf(1));
            this.addProp(property);
        }
    }

    /**
     * 获取角色默认技能
     * @param roleId 角色ID
     * @return
     */
    public DaoMuSkill getRoleDefaultSkill(int roleId) {
        Map<Integer, Integer> roleCollectionMap = this.getRoleMap();
        int curioUnId = roleCollectionMap.get(roleId);
        //藏品配置
        DaoMuCurioConfig daoMuCurioConfig = this.daoMuActivityConfig.getDaoMuCurioConfigMap().get(curioUnId);
        int skillUnId = Integer.valueOf(daoMuCurioConfig.getUnlockSkillLevel());
        //技能信息
        DaoMuSkillConfig daoMuSkillConfig = this.daoMuActivityConfig.getDaoMuSkillConfigMap().get(skillUnId);
        DaoMuSkill daoMuSkill = new DaoMuSkill();
        daoMuSkill.setSkillId(daoMuSkillConfig.getSkillId());
        daoMuSkill.setSkillLevel(daoMuSkillConfig.getLevel());
        daoMuSkill.setCollectionId(daoMuCurioConfig.getCurioId());
        return daoMuSkill;
    }

    /**
     * 获取默认自带技能MAP
     * @return
     */
    public Map<Integer, DaoMuSkill> getDefaultSkillMap() {
        Map<Integer, DaoMuSkill> map = new HashMap<>();
        //角色默认技能
        DaoMuSkill roleSkill = this.getRoleDefaultSkill(this.getRoleId());
        map.put(roleSkill.getSkillId(), roleSkill);
        //自选默认技能
        if (this.getSelectSkillId() > 0) {
            DaoMuSkill selectDefaultSkill = new DaoMuSkill();
            selectDefaultSkill.setSkillId(this.getSelectSkillId());
            selectDefaultSkill.setSkillLevel(1);
            map.put(selectDefaultSkill.getSkillId(), selectDefaultSkill);
        }
        return map;
    }

    /**
     * 获取角色MAP
     * @return Map<Integer, Integer> k:角色ID,V:默认藏品ID
     */
    public Map<Integer, Integer> getRoleMap() {
        //判断是【盗墓笔记】还是【摸金觅宝】
        int goodsType = this.daoMuActivityConfig.getRoleGoodsType();
        Map<Integer, Integer> map = new HashMap<>();
        Map<Integer, GoodsInfo> goodsMap = GoodsMgr.getGoodsMapByType(goodsType);
        for (GoodsInfo goodsInfo : goodsMap.values()) {
            map.put(goodsInfo.getGoodsId(), goodsInfo.getParamList().get(0).intValue());
        }
        return map;
    }

    /**
     * 获取专属藏品，角色对应关系 k:藏品unid，v：角色ID
     * @return
     */
    public Map<Integer, Integer> getCollectionRoleMap() {
        Map<Integer, Integer> map = new HashMap<>();
        List<GoodsInfo> list = TempCommonMgr.getGoodsInfoList();
        int roleGoodsType = this.daoMuActivityConfig.getRoleGoodsType();
        for (GoodsInfo goodsInfo : list) {
            if (goodsInfo.getType() == roleGoodsType) {
                map.put(goodsInfo.getParamList().get(0).intValue(), goodsInfo.getGoodsId());
                map.put(goodsInfo.getParamList().get(1).intValue(), goodsInfo.getGoodsId());
            }
        }
        return map;
    }

    /**
     * 过关
     * @param passesId
     */
    public void pass(int passesId) {
        //判断玩的关卡是当前最高关卡
        if (passesId >= this.getPassesId()) {
            int nextPassesId = daoMuActivityConfig.getNextPassesId(passesId);
            //判断是否通关
            if (nextPassesId == passesId) {
                this.daoMuActivityUserData.setPassAllFlag(1);
            }
            this.daoMuActivityUserData.setPassesId(nextPassesId);
            //盗墓笔记才更新排行，历史最高
            if (this.daoMuActivityConfig.getActivityInfo().getType() == eActivityType.DaoMu.getValue()) {
                //排行变动
                this.notifyPveRank();
                //判断关卡是否是历史最高
                if (passesId > this.getHistoryMaxPassesId()) {
                    setHistoryMaxPassesId(passesId);
                }
            }
        }
    }

    /**
     * 获取玩家PVE排行
     * @return
     */
    public int getPveRank(){
//        CrossActivityRankListModel rankListModel = ActivityRankMgr.getCrossActivityNewRankListModel(this.daoMuActivityConfig.getActivityId(), eGamePlayerEventType.DaoMuPvePersonRank.getValue());
//        int rank = -1;
//        if (rankListModel != null) {
//            rank = rankListModel.getMyRank(this.getUserId(), this.getServerId());
//        }
//        return rank;
        return 0;
    }

    /**
     * 解锁角色
     * @param roleId
     */
    public int unlockRole(int roleId) {
        String rolesStr = this.daoMuActivityUserData.getUnlockRoles();
        Set<String> rolesSet;
        if (StringUtils.isNullOrEmpty(rolesStr)) {
            rolesSet = new HashSet<>();
        } else {
            rolesSet = new HashSet<>(Arrays.asList(rolesStr.split(",")));
        }
        if (!rolesSet.contains(String.valueOf(roleId))) {
            rolesSet.add(String.valueOf(roleId));
            String newStr = String.join(",", rolesSet);
            this.daoMuActivityUserData.setUnlockRoles(newStr);

            //默认角色
            String defaultRoleIdStr = daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.DAOMU_PARTNER_INITIAL_UNLOCK_ITEM_ID);
            int defaultRoleId = Integer.parseInt(defaultRoleIdStr);
            if (defaultRoleId == roleId) {
                //激活专属主动藏品
                GoodsInfo goodsInfo = GoodsMgr.getGoodsById(roleId);
                BigInteger activeCurioUnId = goodsInfo.getParamList().get(0);
                DaoMuCurioConfig activeCurioConfig = daoMuActivityConfig.getDaoMuCurioConfigMap().get(activeCurioUnId.intValue());
                DaoMuActivityUserCollectionData activeCollectionData = this.addCollectionPropNum(activeCurioConfig.getCurioId(), 1);//解锁默认藏品
                activeCollectionData.setCollectionLevel(1);
                //激活专属被动藏品
                BigInteger defaultPassiveCurioUnId = goodsInfo.getParamList().get(1);
                if (defaultPassiveCurioUnId.intValue() > 0) {
                    DaoMuCurioConfig passiveCurioConfig = daoMuActivityConfig.getDaoMuCurioConfigMap().get(defaultPassiveCurioUnId.intValue());
                    DaoMuActivityUserCollectionData passiveCollectionData = this.addCollectionPropNum(passiveCurioConfig.getCurioId(), 1);//解锁默认藏品
                    passiveCollectionData.setCollectionLevel(1);
                }
            } else {
                //赠送的藏品道具
                Property property = new Property();
                //主动藏品道具
                GoodsInfo goodsInfo = GoodsMgr.getGoodsById(roleId);
                BigInteger activeCurioUnId = goodsInfo.getParamList().get(0);
                property.addProperty(activeCurioUnId.intValue(), BigInteger.valueOf(1));
                //被动动藏品道具
                BigInteger defaultPassiveCurioUnId = goodsInfo.getParamList().get(1);
                if (defaultPassiveCurioUnId.intValue() > 0) {
                    property.addProperty(defaultPassiveCurioUnId.intValue(), BigInteger.valueOf(1));
                }
                //添加活动道具
                this.addProp(property);
            }

            //日志
            LogDaoMuRoleUnlock log = new LogDaoMuRoleUnlock();
            log.setActivityId(daoMuActivityConfig.getActivityId());
            log.setUserId(this.getUserId());
            log.setRoleId(roleId);
            log.setCollectionIds("");
            log.setCollectionScore(0);
            log.setAllCollectionScore(this.getCollectionScore());
            AutoLogMgr.add(log);

            return roleId;
        }
        return 0;
    }

    /**
     * 角色角色-领取补发的镶金古玉
     * @param roleId
     * @return
     */
    public int receiveRoleUnlockJadeBf(int roleId) {
        Integer num = this.daoMuActivityUserData.getRoleJadeBfMap().get(String.valueOf(roleId));
        if (num != null) {
            int jadeId = Integer.parseInt(daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.EXCHANGE_SCORE_ITEM_ID));
            Property property = new Property();
            property.addProperty(jadeId,BigInteger.valueOf(num));
            player.getModule(CurrencyModule.class).addCurrency(property, eLogMoneyType.DaoMu, eLogMoneyType.DaoMuRoleUnlockBfJade);
            this.daoMuActivityUserData.removeRoleJadeBf(String.valueOf(roleId));
            return num;
        }
        return 0;
    }

    /**
     * 解锁默认藏品
     */
    public void unlockDefaultCollection() {
        String curioUnIdsStr = this.daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.DAOMU_INITIAL_CURIO_LIST);
        String[] curioUnIdsStrArr = curioUnIdsStr.split("\\|");
        for (String curioUnIdStr :curioUnIdsStrArr) {
            int curioUnId = Integer.valueOf(curioUnIdStr);
            DaoMuCurioConfig daoMuCurioConfig = this.daoMuActivityConfig.getDaoMuCurioConfigMap().get(curioUnId);
            if (daoMuCurioConfig != null) {
                DaoMuActivityUserCollectionData userCollectionData = this.addCollectionPropNum(daoMuCurioConfig.getCurioId(), 1);
                userCollectionData.setCollectionLevel(1);
            }
        }
        //计算藏品分
        this.countCollectionScore();
    }

    /**
     * 是否第一次摸金
     * @return
     */
    private boolean checkFirstTouch() {
        boolean firstTouch = false;
        if (this.daoMuActivityUserData.getDrawBoxNum() == 0) {
            firstTouch = true;
        }
        return firstTouch;
    }

    /**
     * 摸金
     * @param boxId
     * @param num
     * @return
     */
    public DaoMuReward touchGold(int boxId, long num) {
        Property reward = new Property();
        Property activityReward = new Property();
        long collectionScore = 0;
        //摸金
        DaoMuCrowbarBoxConfig daoMuCrowbarBoxConfig = daoMuActivityConfig.getCrowbarBoxConfigMap().get(boxId);
        for (int i = 0; i < num; i++) {
            //镶金古玉
            String weightStr = daoMuCrowbarBoxConfig.getItemWeights();
            String[] weightListArr = weightStr.split("\\|");
            List<Integer> weightList = new ArrayList<>();
            for (String item : weightListArr) {
                String[] itemArr = item.split(",");
                weightList.add(Integer.valueOf(itemArr[1]));
            }
            int index = RandomHelper.getRandomIndexByWeight(weightList);
            if (weightListArr.length > index) {
                //得到镶金古玉
                String rewardStr = weightListArr[index];
                rewardStr = rewardStr.split(",")[0];
                Property addReward = PropertyHelper.parseStringToProperty(rewardStr);
                reward.addProperty(addReward);
            }

            //藏品道具
            int curioUnId;
            if (this.checkFirstTouch()) {
                //第一次摸金,默认给配置的藏品
                String mustCurioUnIdStr = this.daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.DAOMU_GUIDE_BOX_CURIO_ID);
                curioUnId = Integer.parseInt(mustCurioUnIdStr);
            } else {
                //非第一次摸金
                String curioWeightStr = daoMuCrowbarBoxConfig.getCurioWeights();
                String[] curioWeightStrArr = curioWeightStr.split("\\|");
                List<Integer> curioWeightList = new ArrayList<>();
                for (String item : curioWeightStrArr) {
                    String[] itemArr = item.split(",");
                    curioWeightList.add(Integer.valueOf(itemArr[1]));
                }
                int curioIndex = RandomHelper.getRandomIndexByWeight(curioWeightList);
                //得到藏品奖励
                String curioRewardStr = curioWeightStrArr[curioIndex];
                String[] activityRewardArr = curioRewardStr.split(",");
                int curioQuality = Integer.valueOf(activityRewardArr[0]);//藏品品质
                //随机出一个该藏品品质的藏品
                curioUnId = daoMuActivityConfig.getRandomCurioByQuality(curioQuality);
            }
            activityReward.addProperty(curioUnId, BigInteger.valueOf(1));
            DaoMuCurioConfig daoMuCurioConfig = daoMuActivityConfig.getCurioConfig(curioUnId);
            collectionScore += daoMuCurioConfig.getFavoriteScore();
            //增加摸金次数
            this.addTouchBoxNum(1);
        }
        //判断是否有提升镶金古玉的技能
        this.addJadeReward(reward, daoMuActivityConfig);
        //添加活动道具
        if (!activityReward.getGoods().isEmpty()) {
            this.addProp(activityReward);
        }
        //增加背包道具
        if (!reward.getGoods().isEmpty()) {
            player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.DaoMu, eLogMoneyType.DaoMuTouchGoldAddProp);
        }
        //增加进度值
        int addProgress = daoMuCrowbarBoxConfig.getProgressValueAdd() * (int) num;
        int newBoxProgress = this.getBoxProgress() + addProgress;
        this.daoMuActivityUserData.setBoxProgress(newBoxProgress);
        //日志
        LogDaoMuTouchGold log = new LogDaoMuTouchGold();
        log.setActivityId(daoMuActivityConfig.getActivityId());
        log.setUserId(this.getUserId());
        log.setBoxId(boxId);
        log.setNum(num);
        log.setReward(PropertyHelper.parsePropertyToString(reward));
        log.setActivityReward(PropertyHelper.parsePropertyToString(activityReward));
        log.setCollectionScore(collectionScore);
        log.setAllCollectionScore(this.getCollectionScore());
        log.setAddProgress(addProgress);
        log.setBoxProgress(newBoxProgress);
        AutoLogMgr.add(log);
        //返回
        DaoMuReward daoMuReward = new DaoMuReward();
        daoMuReward.setActivityReward(activityReward);
        daoMuReward.setReward(reward);
        return daoMuReward;
    }

    /**
     * 添加角色解锁补发镶金古玉数量
     * @param roleId
     * @param addNum
     */
    private void addRoleJadeBfNum(int roleId, int addNum) {
        Integer num = this.daoMuActivityUserData.getRoleJadeBfMap().get(String.valueOf(roleId));
        if (num == null) {
            num = 0;
        }
        this.daoMuActivityUserData.putRoleJadeBf(String.valueOf(roleId), num + addNum);
    }

    /**
     * 提升【镶金古玉】
     * @param reward
     */
    private void addJadeReward(Property reward, DaoMuActivityConfig daoMuActivityConfig) {
        //【镶金古玉】ID
        int jadeId = Integer.parseInt(daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.EXCHANGE_SCORE_ITEM_ID));
        //提升【镶金古玉】数量
        BigInteger bigInteger = reward.getGoods().get(jadeId);
        if (bigInteger != null) {
            int addNum = 0;
            int num = bigInteger.intValue();
            for (int roleId : this.getRoleMap().keySet()) {
                //获取角色的镶金古玉提示比例
                int roleJadeAddRate = this.getRoleJadeAddRate(roleId);
                if (roleJadeAddRate > 0) {
                    //提升的数量
                    BigDecimal addRate = BigDecimal.valueOf(roleJadeAddRate).divide(BigDecimal.valueOf(1000));
                    BigDecimal oneAddNum = BigDecimal.valueOf(num).multiply(addRate);
                    //判角色是否存在
                    if (this.getUnlockRoleIdSet().contains(roleId)) {
                        //存在，增加镶金古玉提升
                        addNum += oneAddNum.intValue();
                    } else {
                        //不存在，存储镶金古玉提升。后续解锁补发
                        this.addRoleJadeBfNum(roleId, oneAddNum.intValue());
                    }
                }
            }
            //set最终值
            reward.getGoods().put(jadeId, BigInteger.valueOf(num + addNum));
        }
    }

    /**
     * 获取角色的镶金古玉提示比例
     * @param roleId
     * @return
     */
    private int getRoleJadeAddRate(int roleId) {
        //获取角色配置，在goods配置
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(roleId);
        BigInteger curioId = goodsInfo.getParamList().get(2);
        //获取藏品配置
        DaoMuCurioConfig curioConfig = this.daoMuActivityConfig.getCurioConfig(curioId.intValue());
        if (curioConfig != null && curioConfig.getType() == DaoMuCurioTypeEnum.TYPE_JADE_ADD_SKILL.getType()) {
            return Integer.parseInt(curioConfig.getAttributePara());
        }
        return 0;
    }

    /**
     * 开启进度宝箱
     * @return
     * @throws BusinessException
     */
    public String openTouchGoldProgressBox() throws BusinessException {
        //获取宝箱配置
        DaoMuProgressConfig daoMuProgressConfig = daoMuActivityConfig.getProgressConfigMap().get(this.getProgressBoxId());
        int needValue = daoMuProgressConfig.getProgressValue();
        //判断进度值够不够
        if (this.getBoxProgress() < needValue) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_BOX_PROGRESS_NOT_ENOUGH_ERROR);
        }
        //消耗进度值
        int newProgress = this.getBoxProgress() - needValue;
        this.daoMuActivityUserData.setBoxProgress(newProgress);
        //设置下一个宝箱
        this.daoMuActivityUserData.setProgressBoxId(daoMuActivityConfig.geNextProgressBoxId(this.getProgressBoxId()));
        //开启
        return daoMuProgressConfig.getRewards();
    }

    /**
     * 开启全部进度宝箱
     * @return
     */
    public Property openAllTouchGoldProgressBox() {
        Property property = new Property();
        while (true) {
            try {
                String rewardStr = this.openTouchGoldProgressBox();
                property.addProperty(PropertyHelper.parseStringToProperty(rewardStr));
            } catch (BusinessException e) {
                break;
            }
        }
        //增加奖励
        player.getModule(CurrencyModule.class).addCurrency(property, eLogMoneyType.DaoMu, eLogMoneyType.DaoMuProgressBoxAddProp);
        return property;
    }

    /**
     * 存储AND领取悬赏奖励
     * @param passesId
     * @param npcIds
     */
    public void saveAndReceiveOfferReward(int passesId, Set<Integer> npcIds, String roomId) {
        //特色服不悬赏
        if (this.daoMuActivityConfig.getActivityInfo().getType() == eActivityType.DaoMuSpecial.getValue()) {
            return;
        }
        //存储
        boolean saveFlag = this.saveOfferReward(passesId, npcIds, this.daoMuActivityConfig);
        if (saveFlag) {
            //领取
            DaoMuReward daoMuReward = this.autoReceiveOfferReward(passesId);
            if (daoMuReward != null && (daoMuReward.getReward().getGoods().size() > 0 || daoMuReward.getActivityReward().getGoods().size() > 0)) {
                DaoMuReward existReward = this.offerRewardCacheMap.get(roomId);
                if (existReward == null) {
                    existReward = new DaoMuReward();
                }
                existReward.addProperty(daoMuReward.getReward());
                existReward.addActivityProperty(daoMuReward.getActivityReward());
                this.offerRewardCacheMap.put(roomId, existReward);
            }
        }
    }

    /**
     * 存储悬赏信息
     * @param passesId
     * @param npcIds
     */
    public boolean saveOfferReward(int passesId, Set<Integer> npcIds, DaoMuActivityConfig daoMuActivityConfig) {
        int saveNum = 0;
        Map<Integer, DaoMuActivityUserOfferRewardData> offerRewardDataMap = this.getOfferReward(passesId);
        if (offerRewardDataMap == null) {
            offerRewardDataMap = new HashMap<>();
        }
        for (int npcId : npcIds) {
            if (offerRewardDataMap.containsKey(npcId)) {
                continue;
            }
            DaoMuActivityUserOfferRewardData offerRewardData = new DaoMuActivityUserOfferRewardData();
            offerRewardData.setActivityId(daoMuActivityConfig.getActivityId());
            offerRewardData.setUserId(this.getUserId());
            offerRewardData.setPassesId(passesId);
            offerRewardData.setNpcId(npcId);
            offerRewardData.setStatus(DaoMuOfferRewardStatusEnum.NPC_STATUS_NOT_GET.getStatus());
            offerRewardData.setInsertOption();
            offerRewardDataMap.put(npcId, offerRewardData);
            saveNum++;
        }
        this.userOfferRewardDataMap.put(passesId, offerRewardDataMap);
        return saveNum > 0;
    }

    /**
     * 自动悬赏领取奖励
     * @return
     */
    public DaoMuReward autoReceiveOfferReward(int passesId) {
        DaoMuReward result = new DaoMuReward();
        Property reward = new Property();
        Property activityReward = new Property();
        Map<Integer, DaoMuActivityUserOfferRewardData> npcMap = this.userOfferRewardDataMap.get(passesId);
        if (npcMap != null) {
            for (DaoMuActivityUserOfferRewardData data : npcMap.values()) {
                int npcId = data.getNpcId();
                //是否可领取
                if (data.getStatus() != DaoMuOfferRewardStatusEnum.NPC_STATUS_NOT_GET.getStatus()) {
                    continue;
                }
                //奖励信息
                Map<Integer, DaoMuReward> rewardMap = this.daoMuActivityConfig.getPassesOfferReward(passesId);
                DaoMuReward daoMuReward = rewardMap.get(npcId);
                if (daoMuReward == null) {
                    continue;
                }
                //修改状态为已领取
                data.setStatus(DaoMuOfferRewardStatusEnum.NPC_STATUS_GOT.getStatus());
                //请求活动内的道具奖励
                this.addProp(daoMuReward.getActivityReward());
                //背包奖励
                player.getModule(CurrencyModule.class).addCurrency(daoMuReward.getReward(), eLogMoneyType.DaoMu, eLogMoneyType.DaoMuReceiveOfferReward);
                //通知客户端
                DaoMuProto.DaoMuOfferNpcRewardMsg.Builder builder = DaoMuProto.DaoMuOfferNpcRewardMsg.newBuilder();
                builder.setNpcId(npcId);
                builder.setOfferReward(PropertyHelper.parsePropertyToString(daoMuReward.getReward()));
                builder.setOfferActivityReward(PropertyHelper.parsePropertyToString(daoMuReward.getActivityReward()));
                player.sendPacket(Protocol.U_DAOMU_SYNC_OFFER_NPC_REWARD, builder);
                //奖励注入返回结果
                reward.addProperty(daoMuReward.getReward());
                activityReward.addProperty(daoMuReward.getActivityReward());
            }
        }
        result.setReward(reward);
        result.setActivityReward(activityReward);
        return result;
    }

    /**
     * 获取关卡悬赏信息
     * @param passesId 关卡ID
     * @return
     */
    public Map<Integer, DaoMuActivityUserOfferRewardData> getOfferReward(int passesId) {
        return this.userOfferRewardDataMap.get(passesId);
    }

    /**
     * 领取活动奖励
     * @param passesId
     * @param npcId
     * @return
     * @throws BusinessException
     */
    public DaoMuReward receiveOfferReward(int passesId, int npcId) throws BusinessException {
        Map<Integer, DaoMuActivityUserOfferRewardData> offerRewardDataMap = this.getOfferReward(passesId);
        if (offerRewardDataMap == null) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_OFFER_REWARD_NOT_COM_ERROR);
        }
        DaoMuActivityUserOfferRewardData offerRewardData = offerRewardDataMap.get(npcId);
        //是否完成
        if (offerRewardData == null) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_OFFER_REWARD_NOT_COM_ERROR);
        }
        //是否可领取
        if (offerRewardData.getStatus() != DaoMuOfferRewardStatusEnum.NPC_STATUS_NOT_GET.getStatus()) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_OFFER_REWARD_GOT_ERROR);
        }
        //奖励信息
        Map<Integer, DaoMuReward> rewardMap = daoMuActivityConfig.getPassesOfferReward(passesId);
        DaoMuReward daoMuReward = rewardMap.get(npcId);
        if (daoMuReward == null) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_OFFER_REWARD_NOT_SET_ERROR);
        }
        //修改状态为已领取
        offerRewardData.setStatus(DaoMuOfferRewardStatusEnum.NPC_STATUS_GOT.getStatus());
        //请求活动内的道具奖励
        this.addProp(daoMuReward.getActivityReward());
        //返回背包道具
        return daoMuReward;
    }

    /**
     * 获取玩家战斗属性
     * @return
     */
    public Map<Integer, DaoMuAttribute> getAttributeMap() {
        //基础属性
        String basParaStr = this.daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.DAOMU_PARTNER_BASE_PARA);
        Map<Integer, DaoMuAttribute> attributeMap = this.daoMuActivityConfig.buildAttributeMap(basParaStr);
        //加上藏品属性
        for (DaoMuActivityUserCollectionData collectionData : this.userCollectionDataMap.values()) {
            //获取藏品配置
            DaoMuCurioConfig daoMuCurioConfig = this.daoMuActivityConfig.getCollectionInfo(collectionData.getCollectionId(), collectionData.getCollectionLevel());
            if (daoMuCurioConfig == null) {
                continue;
            }
            String attributeStr = daoMuCurioConfig.getBasePara();
            String[] attributeArr = attributeStr.split("\\|");
            for (int i = 0; i < attributeArr.length; i++) {
                String addValueStr = attributeArr[i];
                long addValue = Long.parseLong(addValueStr);
                DaoMuAttribute daoMuAttribute = attributeMap.get(i + 1);
                if (daoMuAttribute != null) {
                    daoMuAttribute.addValue(addValue);
                }
            }
        }
        return attributeMap;
    }

    /**
     * 获取摸金等级
     * @return
     */
    public int countTouchGoldLevel() {
        //藏品分
        long collectionScore = this.getCollectionScore();
        int newLevel = this.daoMuActivityConfig.getTouchGoldLevelByExp(collectionScore);
        //判断等级是否提升
        if (newLevel > this.getTouchGoldLevel()) {
            int oldLevel = this.getTouchGoldLevel();
            this.setTouchGoldLevel(newLevel);
            //日志
            LogDaoMuLevelUpgrade log = new LogDaoMuLevelUpgrade();
            log.setActivityId(this.daoMuActivityConfig.getActivityId());
            log.setUserId(this.getUserId());
            log.setPreLevel(oldLevel);
            log.setLevel(newLevel);
            AutoLogMgr.add(log);
        }
        return newLevel;
    }

    /**
     * 关卡结束处理
     * @param passesId
     * @param status
     * @param offerNpcSet
     * @param pveLevel
     * @param pveSkillIds
     * @param pveBattleTim
     * @param pveKillNum
     * @return
     */
    public DaoMuProto.DaoMuStatementInfoItem.Builder overPasses(int passesId, boolean status, Set<Integer> offerNpcSet,
        int pveLevel, String pveSkillIds, long pveBattleTim, int pveKillNum, String roomId) {
        //是否首次通过
        boolean firstPassFlag = this.checkPassIsFirst(passesId);
        DaoMuReward passesReward = new DaoMuReward();
        if (status && firstPassFlag) {
            //记录首通过的关卡
            this.addFirstRewardPassesId(passesId);
            //过关奖励
            passesReward = daoMuActivityConfig.getPassesReward(passesId, true, true);
            this.addProp(passesReward.getActivityReward());
            player.getModule(CurrencyModule.class).addCurrency(passesReward.getReward(), eLogMoneyType.DaoMu, eLogMoneyType.DaoMuPassPassesReward);
        }
        //获取缓存的悬赏奖领
        DaoMuReward offerReward = this.offerRewardCacheMap.get(roomId);
        if (offerReward == null) {
            offerReward = new DaoMuReward();
        }
        //盗墓笔记才需要计算血脉击杀
        if (this.daoMuActivityConfig.getActivityInfo().getType() == eActivityType.DaoMu.getValue()) {
            //添加关卡杀怪数量
            this.addPassesKillNum(passesId, pveKillNum);
        }
        //判断是否过关
        if (status) {
            //过关
            this.pass(passesId);
        }
        //清空房间
        this.daoMuActivityPveRoom = null;
        this.offerRewardCacheMap = new ConcurrentHashMap<>();
        //日志
        LogDaoMuPassesOver log = new LogDaoMuPassesOver();
        log.setActivityId(this.daoMuActivityConfig.getActivityId());
        log.setUserId(this.getUserId());
        log.setPassesId(passesId);
        log.setRoleId(this.getRoleId());
        log.setRoleLevel(pveLevel);
        log.setSkills(pveSkillIds);
        log.setPassFlag(status ? 1 : 0);
        log.setFirstPassFlag((status && firstPassFlag) ? 1 : 0);
        log.setBattleTime(pveBattleTim);
        log.setReward(PropertyHelper.parsePropertyToString(passesReward.getReward()));
        log.setActivityReward(PropertyHelper.parsePropertyToString(passesReward.getActivityReward()));
        log.setOfferNpcIds(StringUtils.setToString(offerNpcSet, ","));
        log.setOfferReward(PropertyHelper.parsePropertyToString(offerReward.getReward()));
        log.setOfferActivityReward(PropertyHelper.parsePropertyToString(offerReward.getActivityReward()));
        AutoLogMgr.add(log);
        //构造返回PB
        DaoMuStatementInfo daoMuStatementInfo = new DaoMuStatementInfo();
        daoMuStatementInfo.setStatus(status);
        daoMuStatementInfo.setKillNum(pveKillNum);
        daoMuStatementInfo.setBattleTime(pveBattleTim);
        return DaoMuActivityPb.createDaoMuStatementInfoItemPb(daoMuStatementInfo, this, passesReward, offerReward);
    }

    /**
     * 快速过关
     * @param passesId
     * @return
     * @throws BusinessException
     */
    public DaoMuProto.DaoMuStatementInfoItem.Builder quickPass(int passesId) throws BusinessException {
        //判断 历史最高关卡 > 验证关卡
        if (passesId > this.getHistoryMaxPassesId()) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_QUICK_PASS_NOT_DO);
        }
        //判断关卡是否存在
        DaoMuMissionConfig daoMuMissionConfig = daoMuActivityConfig.getDaoMuMissionConfigMap().get(passesId);
        if (daoMuMissionConfig == null) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_PASSES_NOT_EXIST);
        }
        //藏品分是否满足
        if (this.getCollectionScore() < daoMuMissionConfig.getPassFavoriteScore()) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_COLLECTION_SCORE_NOT_ENOUGH);
        }
        //击杀数为：血脉关卡最该击杀数
        int maxNum = this.daoMuActivityConfig.getMobsNumMax(passesId);
        //快速过关
        Set<Integer> npcSet = daoMuActivityConfig.getOfferNpcSet(passesId);
        //领取悬赏奖励
        String roomId = UUIDHelper.randomUUID("daomu");
        this.saveAndReceiveOfferReward(passesId, npcSet, roomId);
        return this.overPasses(passesId, true, npcSet, 0, "", 0, maxNum, roomId);
    }

    /**
     * 获取玩家技能最大等级关系map
     * @param skillMap
     * @return
     */
    public Map<Integer, Integer> getSkillMaxLevelRelation(Map<Integer, DaoMuSkill> skillMap) {
        Map<Integer, Integer> skillMaxLevelMap = new HashMap<>();
        for (DaoMuSkill daoMuSkill : skillMap.values()) {
            //技能最大等级
            String maxSpecialLevelStr = this.daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.DAOMU_LNNING_HAS_ASSISTIVE_SKILL_LEVEL_MAX);
            int fullLevel = Integer.parseInt(maxSpecialLevelStr);
            //玩家藏品信息
            DaoMuActivityUserCollectionData userCollectionData = this.userCollectionDataMap.get(daoMuSkill.getCollectionId());
            if (userCollectionData != null && userCollectionData.getCollectionLevel() > 0) {
                //获取玩家藏品配置
                DaoMuCurioConfig daoMuCurioConfig = this.daoMuActivityConfig.getCollectionInfo(userCollectionData.getCollectionId(), userCollectionData.getCollectionLevel());
                //获取技能配置
                DaoMuSkillConfig daoMuSkillConfig = this.daoMuActivityConfig.getDaoMuSkillConfigMap().get(Integer.valueOf(daoMuCurioConfig.getUnlockSkillLevel()));
                //判断是否有觉醒
                if (daoMuSkillConfig.getLevel() > fullLevel) {
                    fullLevel = daoMuSkillConfig.getLevel();
                }
            }
            skillMaxLevelMap.put(daoMuSkill.getSkillId(), fullLevel);
        }
        return skillMaxLevelMap;
    }

    /**
     * 探索
     * @param passesId
     * @return
     * @throws BusinessException
     */
    public DaoMuActivityPveRoom pveExplore(int passesId) throws BusinessException {
        Map<Integer, DaoMuSkill> defaultSkillMap;
        Map<Integer, DaoMuSkill> skillMap;
        Map<Integer, Integer> skillLevelMap;
        Map<Integer, DaoMuAttribute> attributeMap;
        //判断是盗墓笔记还是盗墓奇遇
        if (this.daoMuActivityConfig.getActivityInfo().getType() == eActivityType.DaoMuSpecial.getValue()) {
            //盗墓奇遇
            DaoMuMissionConfig muMissionConfig = this.daoMuActivityConfig.getDaoMuMissionConfigMap().get(passesId);
            //校验
            String[] unlockArr = muMissionConfig.getUnlock().split(";");
            int passRoadCheck = Integer.valueOf(unlockArr[0]);
            int openServerDayCheck = Integer.valueOf(unlockArr[1]);
            //判断开服天数
            int openServerDay = ServerListMgr.getServerOpenDay(GameServer.getInstance().getServerId());
            if (openServerDayCheck > openServerDay) {
                throw BusinessException.newException(GameErrorCode.E_DAOMU_SPECIAL_SERVER_OPEN_DAY_NOT);
            }
            //判断跑商完成关卡数
            int passRoadId = player.getModule(PassRoadModule.class).getUserPassId();
            if (passRoadCheck > passRoadId) {
                throw BusinessException.newException(GameErrorCode.E_DAOMU_SPECIAL_PASS_ROAD_NOT);
            }
            //获取角色默认技能
            int roleId = muMissionConfig.getPartnerId();
            DaoMuSkill defaultSkill = this.getRoleDefaultSkill(roleId);
            defaultSkillMap = new HashMap<>();
            defaultSkillMap.put(defaultSkill.getSkillId(), defaultSkill);
            int passiveSkillId = daoMuActivityConfig.getPassiveCombSkillId(defaultSkill.getSkillId(), defaultSkill.getSkillLevel());
            //获取技能池
            skillMap = daoMuActivityConfig.getSpecialSkillMap(passesId);
            //主动技能入池
            if (!skillMap.containsKey(defaultSkill.getSkillId())) {
                skillMap.put(defaultSkill.getSkillId(), defaultSkill);
            }
            //被动动技能入池
            if (!skillMap.containsKey(passiveSkillId)) {
                DaoMuSkill daoMuSkill = new DaoMuSkill();
                daoMuSkill.setSkillId(passiveSkillId);
                daoMuSkill.setSkillLevel(1);
                skillMap.put(passiveSkillId, daoMuSkill);
            }
            //技能最高等级关系MAP
            skillLevelMap = daoMuActivityConfig.getSpecialSkillLevelMap(passesId);
            if (!skillLevelMap.containsKey(defaultSkill.getSkillId())) {
                skillLevelMap.put(defaultSkill.getSkillId(), 5);
            }
            //专属技能最高等级，默认5级
            skillLevelMap.put(defaultSkill.getSkillId(), 5);
            skillLevelMap.put(passiveSkillId, 5);
            //获取属性MAP
            String attributeStr = muMissionConfig.getParam();
            attributeMap = this.daoMuActivityConfig.buildAttributeMap(attributeStr);
        } else {
            //盗墓笔记
            //判断关卡是否正确
            if (passesId > this.getPassesId()) {
                throw BusinessException.newException(GameErrorCode.E_DAOMU_PASSES_ERROR);
            }
            //关卡配置
            DaoMuMissionConfig daoMuMissionConfig = this.daoMuActivityConfig.getDaoMuMissionConfigMap().get(passesId);
            if (daoMuMissionConfig == null) {
                throw BusinessException.newException(GameErrorCode.E_DAOMU_PASSES_ERROR);
            }
            //判断藏品分是否达到
            if (this.getCollectionScore() < daoMuMissionConfig.getNeedFavoriteScore()) {
                throw BusinessException.newException(GameErrorCode.E_DAOMU_COLLECTION_SCORE_NOT_ENOUGH);
            }
            //技能池子
            skillMap = this.getUnlockSkillMap();
            //技能-最大等级关系表
            skillLevelMap = this.getSkillMaxLevelRelation(skillMap);
            //默认技能
            defaultSkillMap = this.getDefaultSkillMap();
            //属性map
            attributeMap = this.getAttributeMap();
        }
        this.daoMuActivityPveRoom = new DaoMuActivityPveRoom(this.daoMuActivityConfig, passesId, skillMap, defaultSkillMap, attributeMap, skillLevelMap);
        return this.daoMuActivityPveRoom;
    }

    /**
     * 添加关卡杀怪数量
     * @param passesId
     * @param num
     */
    public void addPassesKillNum(int passesId, int num) {
        Map<String, Integer> passesKillNumMap = this.daoMuActivityUserData.getKillNumJson();
        Integer oldNum = passesKillNumMap.get(String.valueOf(passesId));
        if (oldNum == null) {
            oldNum = 0;
        }
        int newNum = oldNum + num;
        //判断是否超过上限值
        int maxNum = this.daoMuActivityConfig.getMobsNumMax(passesId);
        if (newNum > maxNum) {
            newNum = maxNum;
            num = newNum - oldNum;
        }
        passesKillNumMap.put(String.valueOf(passesId), newNum);
        this.daoMuActivityUserData.setKillNumJson(passesKillNumMap);
        //增加血脉道具,盗墓笔记才加
        if (this.daoMuActivityConfig.getActivityInfo().getChildType() == DaoMuActivityChildTypeEnum.DAOMU.getType()) {
            if (num > 0) {
                Property property = new Property();
                property.setGood(GameConfig.DAOMU_ACTIVITY_ZQL_XM_PROP_ID, BigInteger.valueOf(num));
                player.getModule(CurrencyModule.class).addCurrency(property, eLogMoneyType.DaoMu, eLogMoneyType.DaoMuZqlXmPropAdd);
            }
        }
    }

    /**
     * 同步玩家信息
     */
    public void syncPlayInfoMsg() {
        DaoMuProto.DaoMuPlayerInfo playerInfo = DaoMuActivityPb.createPlayerInfoPb(this);
        DaoMuProto.DaoMuSyncPlayerInfo.Builder msg = DaoMuProto.DaoMuSyncPlayerInfo.newBuilder();
        msg.setActivityId(this.daoMuActivityConfig.getActivityId());
        msg.setPlayerInfo(playerInfo);
        player.sendPacket(Protocol.U_DAOMU_SYNC_PLAYER_INFO, msg);
    }

    /**
     * debug，gm调试方法
     * @param code
     * @param param
     */
    public void debug(String code, String param) {
        if (ServerListMgr.getChannelId(GameServer.getInstance().getServerId()) != 666) {
            return;
        }
        //通关关卡
        if (code.equals("/pveDmPasses")) {
            int passesId = Integer.parseInt(param);
            this.pass(passesId);
            return;
        }
    }

    /**
     * 选择默认技能
     * @param skillId
     * @throws BusinessException
     */
    public void selectDefaultSkill(int skillId) throws BusinessException {
        //判断是否解锁自选默认技能功能,藏品分是否大于最大值
        long collectionScore = Long.parseLong(daoMuActivityConfig.getDaoMuActivityConfigValue(eActivityConfigType.DAOMU_LNNING_SKILL_CARRY_COND));
        if (this.getCollectionScore() < collectionScore) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_COLLECTION_SCORE_NOT_ENOUGH);
        }
        //判断选择的技能是否解锁
        Map<Integer, DaoMuSkill> skillMap = this.getUnlockSkillMap();
        if (!skillMap.containsKey(skillId)) {
            throw BusinessException.newException(GameErrorCode.E_DAOMU_SKILL_NOT_ACT);
        }
        //存储
        this.daoMuActivityUserData.setSelectSkillId(skillId);
    }
}
